From ab3ea9b17eceddd98e9ea58220edc1a4e28353b3 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 3 Sep 2009 07:29:29 +0100 Subject: [PATCH] [IOMMU] dynamic VTd page table for HVM guest This patch makes HVM's VTd page table dynamic just like what PV guest does, so that avoid the overhead of maintaining page table until a PCI device is truly assigned to the HVM guest. Signed-Off-By: Zhai, Edwin --- xen/arch/ia64/xen/domain.c | 2 +- xen/arch/ia64/xen/mm.c | 4 +- xen/arch/x86/mm/hap/p2m-ept.c | 2 +- xen/arch/x86/mm/p2m.c | 2 +- xen/drivers/passthrough/amd/iommu_map.c | 52 ------------------- xen/drivers/passthrough/amd/pci_amd_iommu.c | 2 - xen/drivers/passthrough/iommu.c | 4 +- xen/drivers/passthrough/pci.c | 2 +- xen/include/asm-x86/hvm/svm/amd-iommu-proto.h | 1 - xen/include/xen/sched.h | 2 +- 10 files changed, 9 insertions(+), 64 deletions(-) diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 60b20b5363..854c8b2dee 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -669,7 +669,7 @@ void arch_domain_destroy(struct domain *d) free_xenheap_pages(d->shared_info, get_order_from_shift(XSI_SHIFT)); - if ( iommu_enabled && (is_hvm_domain(d) || need_iommu(d)) ) { + if ( iommu_enabled && need_iommu(d) ) { pci_release_devices(d); iommu_domain_destroy(d); } diff --git a/xen/arch/ia64/xen/mm.c b/xen/arch/ia64/xen/mm.c index de18232388..437ddbca6e 100644 --- a/xen/arch/ia64/xen/mm.c +++ b/xen/arch/ia64/xen/mm.c @@ -1479,7 +1479,7 @@ zap_domain_page_one(struct domain *d, unsigned long mpaddr, if(!mfn_valid(mfn)) return; - if ( iommu_enabled && (is_hvm_domain(d) || need_iommu(d)) ){ + if ( iommu_enabled && need_iommu(d) ){ int i, j; j = 1 << (PAGE_SHIFT-PAGE_SHIFT_4K); for(i = 0 ; i < j; i++) @@ -2885,7 +2885,7 @@ __guest_physmap_add_page(struct domain *d, unsigned long gpfn, smp_mb(); assign_domain_page_replace(d, gpfn << PAGE_SHIFT, mfn, ASSIGN_writable | ASSIGN_pgc_allocated); - if ( iommu_enabled && (is_hvm_domain(d) || need_iommu(d)) ){ + if ( iommu_enabled && need_iommu(d) ){ int i, j; j = 1 << (PAGE_SHIFT-PAGE_SHIFT_4K); for(i = 0 ; i < j; i++) diff --git a/xen/arch/x86/mm/hap/p2m-ept.c b/xen/arch/x86/mm/hap/p2m-ept.c index 1aa0a6ff37..4a2d81bba1 100644 --- a/xen/arch/x86/mm/hap/p2m-ept.c +++ b/xen/arch/x86/mm/hap/p2m-ept.c @@ -282,7 +282,7 @@ out: ept_sync_domain(d); /* Now the p2m table is not shared with vt-d page table */ - if ( iommu_enabled && is_hvm_domain(d) && need_modify_vtd_table ) + if ( iommu_enabled && need_iommu(d) && need_modify_vtd_table ) { if ( p2mt == p2m_ram_rw ) { diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index 91b148b2dd..c10b31b566 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -1199,7 +1199,7 @@ p2m_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn, && (gfn + (1UL << page_order) - 1 > d->arch.p2m->max_mapped_pfn) ) d->arch.p2m->max_mapped_pfn = gfn + (1UL << page_order) - 1; - if ( iommu_enabled && (is_hvm_domain(d) || need_iommu(d)) ) + if ( iommu_enabled && need_iommu(d) ) { if ( p2mt == p2m_ram_rw ) for ( i = 0; i < (1UL << page_order); i++ ) diff --git a/xen/drivers/passthrough/amd/iommu_map.c b/xen/drivers/passthrough/amd/iommu_map.c index 3d051d4696..9754f4b1ed 100644 --- a/xen/drivers/passthrough/amd/iommu_map.c +++ b/xen/drivers/passthrough/amd/iommu_map.c @@ -555,58 +555,6 @@ int amd_iommu_reserve_domain_unity_map( return 0; } -int amd_iommu_sync_p2m(struct domain *d) -{ - unsigned long mfn, gfn; - u64 iommu_l2e; - struct page_info *page; - struct hvm_iommu *hd; - int iw = IOMMU_IO_WRITE_ENABLED; - int ir = IOMMU_IO_READ_ENABLED; - - if ( !is_hvm_domain(d) ) - return 0; - - hd = domain_hvm_iommu(d); - - spin_lock(&hd->mapping_lock); - - if ( hd->p2m_synchronized ) - goto out; - - spin_lock(&d->page_alloc_lock); - - page_list_for_each ( page, &d->page_list ) - { - mfn = page_to_mfn(page); - gfn = get_gpfn_from_mfn(mfn); - - if ( gfn == INVALID_M2P_ENTRY ) - continue; - - iommu_l2e = iommu_l2e_from_pfn(hd->root_table, hd->paging_mode, gfn); - - if ( iommu_l2e == 0 ) - { - spin_unlock(&d->page_alloc_lock); - spin_unlock(&hd->mapping_lock); - amd_iov_error("Invalid IO pagetable entry gfn = %lx\n", gfn); - domain_crash(d); - return -EFAULT; - } - - set_iommu_l1e_present(iommu_l2e, gfn, (u64)mfn << PAGE_SHIFT, iw, ir); - } - - spin_unlock(&d->page_alloc_lock); - - hd->p2m_synchronized = 1; - -out: - spin_unlock(&hd->mapping_lock); - return 0; -} - void invalidate_all_iommu_pages(struct domain *d) { u32 cmd[4], entry; diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c index 7ab82d9912..70683d24e2 100644 --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c @@ -311,8 +311,6 @@ static int amd_iommu_assign_device(struct domain *d, u8 bus, u8 devfn) int bdf = (bus << 8) | devfn; int req_id = ivrs_mappings[bdf].dte_requestor_id; - amd_iommu_sync_p2m(d); - if ( ivrs_mappings[req_id].unity_map_enable ) { amd_iommu_reserve_domain_unity_map( diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c index b0dd91d66c..6933e658fe 100644 --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -137,7 +137,7 @@ int assign_device(struct domain *d, u8 bus, u8 devfn) if ( (rc = hd->platform_ops->assign_device(d, bus, devfn)) ) goto done; - if ( has_arch_pdevs(d) && !is_hvm_domain(d) && !need_iommu(d) ) + if ( has_arch_pdevs(d) && !need_iommu(d) ) { d->need_iommu = 1; rc = iommu_populate_page_table(d); @@ -184,7 +184,7 @@ void iommu_domain_destroy(struct domain *d) if ( !iommu_enabled || !hd->platform_ops ) return; - if ( !is_hvm_domain(d) && !need_iommu(d) ) + if ( !need_iommu(d) ) return; if ( need_iommu(d) ) diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c index bf47ae97b8..843324598b 100644 --- a/xen/drivers/passthrough/pci.c +++ b/xen/drivers/passthrough/pci.c @@ -202,7 +202,7 @@ static void pci_clean_dpci_irqs(struct domain *d) if ( !iommu_enabled ) return; - if ( !is_hvm_domain(d) && !need_iommu(d) ) + if ( !need_iommu(d) ) return; spin_lock(&d->event_lock); diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h index 9d1ef04097..3e972cf655 100644 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h @@ -63,7 +63,6 @@ int amd_iommu_unmap_page(struct domain *d, unsigned long gfn); u64 amd_iommu_get_next_table_from_pte(u32 *entry); int amd_iommu_reserve_domain_unity_map(struct domain *domain, unsigned long phys_addr, unsigned long size, int iw, int ir); -int amd_iommu_sync_p2m(struct domain *d); void invalidate_all_iommu_pages(struct domain *d); /* device table functions */ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index be15f3307f..d37c83fccb 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -557,7 +557,7 @@ uint64_t get_cpu_idle_time(unsigned int cpu); #define is_hvm_domain(d) ((d)->is_hvm) #define is_hvm_vcpu(v) (is_hvm_domain(v->domain)) -#define need_iommu(d) ((d)->need_iommu && !(d)->is_hvm) +#define need_iommu(d) ((d)->need_iommu) void set_vcpu_migration_delay(unsigned int delay); unsigned int get_vcpu_migration_delay(void); -- 2.30.2